package com.orangelife.service.propFeeComputeRule.model;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.orangelife.utils.FormulaUtil;
import com.orangelife.utils.StringUtils;

public class Rule {

	public static void main(String[] args) {

		Rule r = new Rule();

		r.setRule("1;*;1;+;@@@1212(12)");
		r.init();
		r.getParam().put("@@@1212(12)", "-2");
		System.out.println(r.getSuffixExpression() + "&&&");

		System.out.println(r.complete(r.param) + "&&&&1111111111");

		System.out.println("sdsdf".indexOf(""));
		int i = 0;
		// while (true) {
		//
		// GregorianCalendar gc = new GregorianCalendar();
		// try {
		// gc.setTime(new SimpleDateFormat("yyyy-MM").parse("2016-07"));
		// } catch (ParseException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }
		// gc.add(2, i);
		// String feedate = new SimpleDateFormat("yyyy-MM").format(gc
		// .getTime());
		// if (Integer.parseInt(feedate.replaceAll("-", "")) > Integer
		// .parseInt("2017-07".replaceAll("-", ""))) {
		// break;
		// }
		//
		// System.out.println(feedate);
		// i++;
		// }
	}

	private static final long serialVersionUID = 1L;

	/**
	 * 
	 * 规则id*
	 **/
	private String ruleID;

	/**
	 * 
	 * 小区id*
	 **/
	private String commID;

	private String compRule;

	/**
	 * 
	 * 规则名称*
	 **/
	private String ruleName;

	/**
	 * 
	 * 收费类目*
	 **/
	private String feeTypeID;

	/**
	 * 
	 * 收费类目名称*
	 **/
	private String feeTypeName;

	/**
	 * 
	 * 收费类目类型 （固定 和计量类的添加单价和量）
	 */

	private String feeType;

	/**
	 * 收费类目编码
	 * 
	 * */

	private String feeCode;
	/**
	 * 
	 * 收费类目类型 （固定 和计量类的添加单价和量）
	 */

	private String feeAmount;
	/**
	 * 
	 * 收费类目类型 （固定 和计量类的添加单价和量）
	 */

	private String feePrice;

	/**
	 * 
	 * 规则类型*
	 **/
	private String ruleType;

	/**
	 * 
	 * 规则*
	 **/
	private String rule;

	/**
	 * 
	 * 进位类型 1四舍五入（默认）2舍去*
	 **/
	private String roundType;

	/**
	 * 
	 * 小数点后*
	 **/
	private Integer round;

	private String initID;

	/**
	 * 
	 * 生成周期(1按月，2按季)*
	 **/
	private String periodType;

	/**
	 * 
	 * 当前生成日期*
	 **/
	private String curDate;

	/**
	 * 
	 * 状态*
	 **/
	private String status;

	/**
	 * 
	 * 创建时间*
	 **/
	private java.util.Date tscreate;

	/**
	 * 
	 * 修改时间*
	 **/
	private java.util.Date tsedit;

	/**
	 * 
	 * 是否有效*
	 **/
	private String itemStat;

	/**
	 * 
	 * 创建者*
	 **/
	private String createuserID;

	/**
	 * 
	 * 修改者*
	 **/
	private String edituserID;

	/**
	 * 
	 * 有效期类型（1永久有效2时间段内有效,3一次性）
	 **/
	private String validityType;
	/**
	 * 
	 * 临时开始时间*
	 **/
	private String startTime;

	/**
	 * 
	 * 临时结束时间*
	 **/
	private String endTime;

	private int isValid = 0;
	/**
	 * 
	 * 规则的后缀表达式(;号隔开)
	 **/
	private String suffixExpression;

	/**
	 * 
	 * 解析后的需外部获取参数数组
	 **/
	private Map<String, String> Extparam;

	/**
	 * 
	 * 解析后的需外部获取参数数组
	 **/
	private boolean isInit = false;

	/**
	 * 
	 * 计算时填入的参数()
	 **/
	private Map<String, String> param = new HashMap<>();

	/**
	 * 
	 * 计算时需填入的参数(包含公式中需要的参数)
	 **/
	private Set<String> activeParam;

	private boolean isCache = false;;
	/**
	 * 
	 * 楼层系数
	 * */
	private Ratio ratio;

	/**
	 * 
	 * 固定参数替换过的表达式（实现缓存固定参数）
	 **/
	private String cacheExpression;

	/**
	 * 
	 * 要生成账单的开始时间
	 **/
	private String startDate;
	/**
	 * 
	 * 要生成账单的结束时
	 **/
	private String endDate;
	/**
	 * 
	 * 校验结果
	 **/

	private boolean checkRes;

	/**
	 * 
	 * 校验结果说明
	 **/

	private String errInfo;

	/**
	 * 
	 * 是否每月生成 1开始月份，2结束月份，3每月 默认为 2
	 **/

	private int isEvery = 2;

	// private String feeTy

	private String Date;

	public void init(boolean checkEmpty) {
		if (checkEmpty) {
			this.init();

		} else {
			this.check(false);
			this.ruleToSuffix();
			this.dealRuleParam();
			this.setAmountAndPrice();
		}

	}

	public void init() {

		if (this.check(true)) {
			this.ruleToSuffix();
			this.dealRuleParam();
			this.setAmountAndPrice();
		}
		;

	}

	private void setAmountAndPrice() {
		// ||"2".equals(this.feeType)"0,1,2,3".indexOf(StringUtils.toString(this.feeCode,
		// ""))!=-1&&

	}

	/**
	 * 
	 * 验证参数是否有效checkEmpty 当rule为空时是否校验当无效时设置状态为无效
	 **/
	private boolean check(boolean checkEmpty) {
		this.setIsValid(-1);
		if (this.rule == null || "".equals(this.rule.trim())) {
			if (checkEmpty) {

				return false;
			}
			this.setIsValid(1);
			return true;

		}

		if (FormulaUtil.check(this.rule)) {

			this.setIsValid(1);
			return true;
		}

		return false;

		// return true;
	}

	/**
	 * 
	 * 规则解析成后缀表达式
	 * */
	private void ruleToSuffix() {

		this.suffixExpression = FormulaUtil.inTosuffix(this.rule);

		this.cacheExpression = this.suffixExpression;
	}

	/**
	 * 
	 * 解析参数后设置需外部获取参数数组 @@@为自定公式
	 * */
	private void dealRuleParam() {

		String[] param = this.rule.split(";");

		this.Extparam = new HashMap<>();
		this.activeParam = new HashSet<>();
		for (String string : param) {
			if (string.indexOf("@@@") != -1) {

			} else if (string.startsWith("@")) {

				this.Extparam.put(string, null);
				this.activeParam.add(string);
			}

		}

	}

	/**
	 * 
	 * 设置固定参数
	 * */
	public void setCache(Map<String, String> fixParam) {

		this.cacheExpression = this.suffixExpression;
		this.activeParam = new HashSet<>();

		for (String param : this.Extparam.keySet()) {

			if (fixParam.containsKey(param)
					&& StringUtils.isDouble(fixParam.get(param))) {
				this.cacheExpression = this.cacheExpression.replace(
						param + ";", fixParam.get(param + ";"));
			} else {
				this.activeParam.add(param);
			}

		}
		this.isCache = true;

	}

	/**
	 * 
	 * 添加单个固定参数
	 * */
	public void setCache(String param, String value) {

		if (this.activeParam.contains(param) && StringUtils.isDouble(value)) {

			this.cacheExpression = this.cacheExpression.replace(param + ";",
					value + ";");
			activeParam.remove(param);

		}

		this.isCache = true;

	}

	public String completeString(Map<String, String> param) {
		String l = null;
		if (this.isCache) {
			l = this.cacheExpression;

			for (String p : this.activeParam) {
				if (param.containsKey(p) && StringUtils.isDouble(param.get(p))) {
					l = l.replace(p + ";", param.get(p) + ";");
				} else {

					return null;
				}
			}

		} else {

			l = this.suffixExpression;

			for (String p : this.Extparam.keySet()) {
				if (param.containsKey(p) && StringUtils.isDouble(param.get(p))) {
					l = l.replace(p + ";", param.get(p) + ";");
				} else {

					return null;
				}
			}

		}

		return FormulaUtil.completeString(l);

	}

	public BigDecimal complete(Map<String, String> param) {
		String l = null;
		if (this.isCache) {
			l = this.cacheExpression;

			for (String p : this.activeParam) {
				if (param.containsKey(p) && StringUtils.isDouble(param.get(p))) {
					l = l.replace(p + ";", param.get(p) + ";");
				} else {

					return null;
				}
			}

		} else {

			l = this.suffixExpression;

			for (String p : this.Extparam.keySet()) {
				if (param.containsKey(p) && StringUtils.isDouble(param.get(p))) {
					l = l.replace(p + ";", param.get(p) + ";");
				} else {

					return null;
				}
			}

		}

		return FormulaUtil.complete(l);

	}

	// 按下一期
	public List<String> getResList(String res) throws ParseException {

		boolean flag = false;
		if ("2".equals(this.periodType)) {

			flag = true;

		}

		if (this.isEvery == 1) {

			return this.getResList(res, this.getStartDate(),
					this.getStartDate(), flag);

		}

		if (this.isEvery == 3) {

			return this.getResList(res, this.getStartDate(), this.getEndDate(),
					false);

		}
		// 按下一期
		return this.getResList(res, this.getEndDate(), this.getEndDate(), flag);

	}

	// 按阶段
	public List<String> getResList2(String res) throws ParseException {

		// flag=true 则按 3 6 9 12
		boolean flag = false;

		if ("2".equals(this.periodType)) {

			flag = true;

		}

		if (this.isEvery == 3) {

			return this.getResList(res, this.getStartDate(), this.getEndDate(),
					false);

		}
		return this.getResList(res, this.getStartDate(), this.getEndDate(),
				flag);

	}

	public List<String> getResList(String res, String startTime,
			String endTime, boolean flag) throws ParseException {

		List<String> r = new ArrayList<>();
		int i = 0;
		while (true) {

			GregorianCalendar gc = new GregorianCalendar();

			gc.setTime(new SimpleDateFormat("yyyy-MM").parse(startTime));

			gc.add(2, i);
			String feedate = new SimpleDateFormat("yyyy-MM").format(gc
					.getTime());
			if (Integer.parseInt(feedate.replaceAll("-", "")) > Integer
					.parseInt(endTime.replaceAll("-", ""))) {
				break;
			}

			if (flag) {

				if ("03060912".indexOf(feedate.substring(5)) != -1) {
					r.add(feedate);

				}

			} else {
				r.add(feedate);

			}

			i++;
		}
		return r;

	}

	public void setRuleID(String ruleID) {
		this.ruleID = ruleID;
	}

	public String getRuleID() {
		return ruleID;
	}

	public void setCommID(String commID) {
		this.commID = commID;
	}

	public String getCommID() {
		return commID;
	}

	public void setRuleName(String ruleName) {
		this.ruleName = ruleName;
	}

	public String getRuleName() {
		return ruleName;
	}

	public void setFeeTypeID(String feeTypeID) {
		this.feeTypeID = feeTypeID;
	}

	public String getFeeTypeID() {
		return feeTypeID;
	}

	public void setRuleType(String ruleType) {
		this.ruleType = ruleType;
	}

	public String getRuleType() {
		return ruleType;
	}

	public void setRule(String rule) {
		this.rule = rule;
	}

	public String getRule() {
		return rule;
	}

	public void setRoundType(String roundType) {
		this.roundType = roundType;
	}

	public String getRoundType() {
		return roundType;
	}

	public void setRound(Integer round) {
		this.round = round;
	}

	public Integer getRound() {
		return round;
	}

	public void setPeriodType(String periodType) {
		this.periodType = periodType;
	}

	public String getPeriodType() {
		return periodType;
	}

	public void setCurDate(String curDate) {
		this.curDate = curDate;
	}

	public String getCurDate() {
		return curDate;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getStatus() {
		return status;
	}

	public void setTscreate(java.util.Date tscreate) {
		this.tscreate = tscreate;
	}

	public java.util.Date getTscreate() {
		return tscreate;
	}

	public void setTsedit(java.util.Date tsedit) {
		this.tsedit = tsedit;
	}

	public java.util.Date getTsedit() {
		return tsedit;
	}

	public void setItemStat(String itemStat) {
		this.itemStat = itemStat;
	}

	public String getItemStat() {
		return itemStat;
	}

	public void setCreateuserID(String createuserID) {
		this.createuserID = createuserID;
	}

	public String getCreateuserID() {
		return createuserID;
	}

	public void setEdituserID(String edituserID) {
		this.edituserID = edituserID;
	}

	public String getEdituserID() {
		return edituserID;
	}

	public String getPostfixExpression() {
		return suffixExpression;
	}

	public void setPostfixExpression(String postfixExpression) {
		this.suffixExpression = postfixExpression;
	}

	public Map<String, String> getExtparam() {
		return Extparam;
	}

	public void setExtparam(Map<String, String> extparam) {
		Extparam = extparam;
	}

	public Set<String> getActiveParam() {
		return activeParam;
	}

	public void setActiveParam(Set<String> activeParam) {
		this.activeParam = activeParam;
	}

	public String getCacheExpression() {
		return cacheExpression;
	}

	public void setCacheExpression(String cacheExpression) {
		this.cacheExpression = cacheExpression;
	}

	public Map<String, String> getParam() {
		return param;
	}

	public void setParam(Map<String, String> param) {
		this.param = param;
	}

	public String getStartDate() {
		return startDate;
	}

	public void setStartDate(String startDate) {
		this.startDate = startDate;
	}

	public String getDate() {
		return Date;
	}

	public void setDate(String date) {
		Date = date;
	}

	public boolean getCheckRes() {
		return checkRes;
	}

	public void setCheckRes(boolean checkRes) {
		this.checkRes = checkRes;
	}

	public String getErrInfo() {
		return errInfo;
	}

	public void setErrInfo(String errInfo) {
		this.errInfo = errInfo;
	}

	public String getEndDate() {
		return endDate;
	}

	public void setEndDate(String endDate) {
		this.endDate = endDate;
	}

	public int getIsValid() {
		return isValid;
	}

	public void setIsValid(int isValid) {
		this.isValid = isValid;
	}

	public boolean isInit() {
		return isInit;
	}

	public void setInit(boolean isInit) {
		this.isInit = isInit;
	}

	public String getSuffixExpression() {
		return suffixExpression;
	}

	public void setSuffixExpression(String suffixExpression) {
		this.suffixExpression = suffixExpression;
	}

	public boolean isCache() {
		return isCache;
	}

	public void setCache(boolean isCache) {
		this.isCache = isCache;
	}

	public Ratio getRatio() {
		return ratio;
	}

	public void setRatio(Ratio ratio) {
		this.ratio = ratio;
	}

	public String getFeeTypeName() {
		return feeTypeName;
	}

	public void setFeeTypeName(String feeTypeName) {
		this.feeTypeName = feeTypeName;
	}

	public int getIsEvery() {
		return isEvery;
	}

	public void setIsEvery(int isEvery) {
		this.isEvery = isEvery;
	}

	public String getValidityType() {
		return validityType;
	}

	public void setValidityType(String validityType) {
		this.validityType = validityType;
	}

	public String getStartTime() {
		return startTime;
	}

	public void setStartTime(String startTime) {
		this.startTime = startTime;
	}

	public String getEndTime() {
		return endTime;
	}

	public void setEndTime(String endTime) {
		this.endTime = endTime;
	}

	public String getFeeType() {
		return feeType;
	}

	public void setFeeType(String feeType) {
		this.feeType = feeType;
	}

	public String getFeeAmount() {
		return feeAmount;
	}

	public void setFeeAmount(String feeAmount) {
		this.feeAmount = feeAmount;
	}

	public String getFeePrice() {
		return feePrice;
	}

	public void setFeePrice(String feePrice) {
		this.feePrice = feePrice;
	}

	public String getFeeCode() {
		return feeCode;
	}

	public void setFeeCode(String feeCode) {
		this.feeCode = feeCode;
	}

	public String getInitID() {
		return initID;
	}

	public void setInitID(String initID) {
		this.initID = initID;
	}

	public String getCompRule() {
		return compRule;
	}

	public void setCompRule(String compRule) {
		this.compRule = compRule;
	}

}
